/*
 * DigitalIO.c
 *
 *  Created on: Oct 28, 2011
 *      Author: Philip Rodriguez, Alfred Lee, Oliver Wing
 *
 *  Output data from A/D converter to digital IO
 */

#include "DigitalIO.h"
#include "types.h"

// handles to the Digital IO
uintptr_t dioControlHandle;
uintptr_t adDataHandle;
uintptr_t statusHandle;
uintptr_t readySignalHandle;

// The status byte from the QNX containing (currently) two flags
UINT8 statusByte;

// Initialize the settings for the Digital IO
void initDigitalIORegister(void)
{
	// get a handle to the Digital IO control register
	dioControlHandle = mmap_device_io(PORT_LENGTH, DIO_CTRL_ADDRESS);

	// get a handle to Port A on the Digital IO
	adDataHandle = mmap_device_io(PORT_LENGTH, PORTA_ADDRESS);

	// get a handle to Port B on the Digital IO
	readySignalHandle = mmap_device_io(PORT_LENGTH, PORTB_ADDRESS);

	// get a handle to Port C on the Digital IO
	statusHandle = mmap_device_io(PORT_LENGTH, PORTC_ADDRESS);

	// configure the Digital IO channels for sending data
	out8(dioControlHandle, PORTC_BEHAVIOR | PORTB_DIRECTION);

	// Initialize status byte to no special messages
	statusByte = 0;

	// Initialize Port C to no special status
	OutputStatus();
}

// Send a signal to Freescale that QNX is ready to
// send the data from the conversion
void outputReadySignal(UINT8 readySignalData)
{
	out8(readySignalHandle, readySignalData);
}

// Send the digital data to the Digital IO ports
void sendData(INT16 digitalData)
{
	INT8 dataToSend = (digitalData >> 8);
	out8(adDataHandle, dataToSend);
}


// Quasi-POST test to verify proper setup of the DAQ output ports
bool POSTOutputDAQ() {
	// Check that the output data ports can receive data.
	UINT8 testIn;

	// Write a byte out to the ports
	out8( adDataHandle, TEST_VAL );
	// Read the byte back in: the DIO ports are set as write-only,
	// but reading it will return the last byte sent
	testIn = in8( adDataHandle );
	// Fail if not equal to byte sent to port.
	if ( testIn != TEST_VAL )
	{
		return false;
	}

	// Write a byte out to the ports
	out8( statusHandle, TEST_VAL );
	// Read the byte back in: the DIO ports are set as write-only,
	// but reading it will return the last byte sent
	testIn = in8( statusHandle );
	// Fail if not equal to byte sent to port.
	if ( testIn != TEST_VAL )
	{
		return false;
	}

	// No POSTs failed here.
	return true;
}


// Various status messages which will indicate an error
// through an LED to the user

// Output the current status to an LED
void OutputStatus()
{
	out8( statusHandle, statusByte );
}

// There is a problem with the connection
void RaiseConnectionError()
{
	statusByte |= STATUS_CONNECTION_ERROR;
}

// There is no problem with the connection
void ClearConnectionError()
{
	statusByte &= ~STATUS_CONNECTION_ERROR;
}

// A voltage has exceeded the [-5, +5] V range
void RaiseVoltageWarning()
{
	statusByte |= STATUS_VOLTAGE_WARNING;
}

// There is no problem with the voltage being out of range
void ClearVoltageWarning()
{
	statusByte &= ~STATUS_VOLTAGE_WARNING;
}

// The digital data from conversion is ready to send
void ConversionResultReady()
{
	statusByte |= STATUS_CONVERSION_READY;
}

// The A/D conversion is being performed
void ConversionInProgress()
{
	statusByte &= ~STATUS_CONVERSION_READY;
}

// The POSTs failed.
void RaisePOSTSuccess()
{
	statusByte |= STATUS_POST_SUCCESS;
}

// The POSTs passed.
void ClearPOSTSuccess()
{
	statusByte &= ~STATUS_POST_SUCCESS;
}
